﻿using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Collections.Generic;

namespace DotNetAgent.Core
{
	public class FileLogConnector : IDisposable
	{
		private Agent _i_Owner = null;
		protected Agent i_Owner
		{
			get { return _i_Owner; }
		}

		protected string LogFilename;
		public static string LogFilePath = Assembly.GetExecutingAssembly().Location.Remove(Assembly.GetExecutingAssembly().Location.LastIndexOf(@"\") + 1);

		public FileLogConnector(Agent p_Owner, Dictionary<String, Object> p_Args)
		{
			try
			{
				_i_Owner = p_Owner;
				if (i_Owner == null)
				{
					throw new AgentException("Activation", "Owner not specified");
				}
				if (!p_Args.ContainsKey("LogFilename"))
				{
					throw new AgentException("Activation", "LogFilename not specified");
				}
				LogFilename = p_Args["LogFilename"] as String;
				WriteLogStart();
			}
			catch (Exception ex)
			{
				throw new AgentException("Activation", "Error During LogAgent Activation", ex);
			}
		}

		public void Dispose()
		{
			WriteLogEnd();
		}

		public static void DebugLog(string Msg)
		{
			try
			{
				File.AppendAllText(LogFilePath + "DotNetAgent-debug.log", Environment.NewLine + "[" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "]\t" + Msg, Encoding.UTF8);
			}
			catch (Exception)
			{
			}
		}

		public static void DebugLog(string Msg, Exception Ex)
		{
			DebugLog(Msg + ": " + AgentException.FormatExceptionString(Ex));
		}

		public static string GetLogFilepath()
		{
			return Assembly.GetExecutingAssembly().Location.Remove(Assembly.GetExecutingAssembly().Location.LastIndexOf(@"\") + 1);
		}

		public void Log(String Source, DateTime TimeStamp, string OperationName, string Category, string Msg)
		{
			WriteLogFile(Environment.NewLine + TimeStamp.ToString("yyyy-MM-dd HH:mm:ss.fff").PadRight(24, ' ') + "|" + Category.PadRight(13, ' ') + "|" + Source.PadRight(42, ' ') + "|" + OperationName.PadRight(32, ' ') + "|" + Msg.PadRight(15, ' '));
		}

		public void LogInfo(String Source, string OperationName, string Msg)
		{
			Log(Source, DateTime.Now, OperationName, "Information", Msg);
		}

		public void LogWarning(String Source, string OperationName, string Msg)
		{
			Log(Source, DateTime.Now, OperationName, "Warning", Msg);
		}

		public void LogError(String Source, string OperationName, string Msg, Exception Ex)
		{
			Log(Source, DateTime.Now, OperationName, "Error", Msg + Environment.NewLine + AgentException.FormatExceptionString(Ex));
		}

		public void WriteLogEnd()
		{
			try
			{
				WriteLogFile(Environment.NewLine + "".PadRight(24, '-') + "|" + "".PadRight(13, '-') + "|" + "".PadRight(42, '-') + "|" + "".PadRight(32, '-') + "|" + "".PadRight(79, '-'));
			}
			catch (Exception Ex)
			{
				throw new AgentException("WriteLogEnd", "Error During Log Writing End", Ex);
			}
		}

		protected void WriteLogFile(string Msg)
		{
			try
			{
				for (int retries = 0; retries < 10; retries++)
				{
					try
					{
						File.AppendAllText(LogFilename, Msg, Encoding.UTF8);
						break;
					}
					catch (Exception)
					{
						Agent.Sleep(100 * retries);
					}
				}
			}
			catch (Exception _Ex)
			{
				throw new AgentException("WriteLog", "Error During Writer Log Writing", _Ex);
			}
		}

		public void WriteLogStart()
		{
			try
			{
				WriteLogFile(Environment.NewLine + "-TIMESTAMP".PadRight(24, '-') + "|-CATEGORY".PadRight(14, '-') + "|-SOURCE".PadRight(43, '-') + "|-OPERATION".PadRight(33, '-') + "|-MESSAGE [PROPERTIES]".PadRight(80, '-'));
				WriteLogFile(Environment.NewLine + "".PadRight(24, '-') + "|" + "".PadRight(13, '-') + "|" + "".PadRight(42, '-') + "|" + "".PadRight(32, '-') + "|" + "".PadRight(79, '-'));
			}
			catch (Exception Ex)
			{
				throw new AgentException("WriteLogStart", "Error During Log Writing Start", Ex);
			}
		}
	}
}